﻿#include "hardwareeditorpresenter.h"

/**
 * @brief HardwareEditorPresenter::HardwareEditorPresenter
 * @details 初始化 Presenter，保存模板数据和连接图视图指针。
 * @param doc 硬件模板数据。
 * @param connView 连接图视图。
 * @param parent Qt 父对象。
 */
HardwareEditorPresenter::HardwareEditorPresenter(HardwareTemplatePtr doc,
                                                 ConnectingWindow *connView,
                                                 QObject *parent)
    : QObject(parent)
    , doc_(doc)
    , conn_(connView)
{
}

/**
 * @brief HardwareEditorPresenter::bind
 * @details 绑定连接图的节点事件与型号同步信号。
 */
void HardwareEditorPresenter::bind()
{
    if (!conn_ || !doc_)
        return;
    connect(conn_, &ConnectingWindow::sig_nodeToggled, this, &HardwareEditorPresenter::onNodeToggled);
    connect(conn_, &ConnectingWindow::sig_syncModel, this, &HardwareEditorPresenter::onNodeModelSync);
}

// 动态挂载/解绑全局属性面板
/**
 * @brief HardwareEditorPresenter::setAttrView
 * @details 动态挂载或解绑属性面板，并同步当前数据。
 * @param attr 属性面板适配器。
 */
void HardwareEditorPresenter::setAttrView(AttributePanelAdapter *attr)
{
    if (attr_ == attr)
        return;

    if (attr_) {
        // 解绑旧面板信号
        disconnect(attr_, nullptr, this, nullptr);
    }
    attr_ = attr;

    if (attr_) {
        //        connect(attr_, &AttributePanelAdapter::modelEdited, this, &HardwareEditorPresenter::onModelEdited);
        connect(attr_, &AttributePanelAdapter::interfaceEdited, this, &HardwareEditorPresenter::onInterfaceEdited);
        connect(attr_, &AttributePanelAdapter::addressEdited, this, &HardwareEditorPresenter::onAddressEdited);
        refreshAttrPanel(); // 切换tab时立即把当前role的数据灌入右侧面板
    }
}

/**
 * @brief HardwareEditorPresenter::save
 * @details 调用数据管理器保存当前模板。
 * @param err 失败时返回错误字符串。
 * @return 成功与否。
 */
bool HardwareEditorPresenter::save(QString *err)
{
    if (!doc_) {
        if (err)
            *err = "null doc";
        return false;
    }
    bool ok = DataManager::instance()->updateHardwareTemplate(doc_);
    if (!ok && err)
        *err = "updateHardwareTemplate failed";
    return ok;
}

/**
 * @brief HardwareEditorPresenter::selectedRole
 * @details 返回当前选中的设备角色。
 * @return 设备角色。
 */
DeviceRole HardwareEditorPresenter::selectedRole() const
{
    return selectedRole_;
}
/**
 * @brief HardwareEditorPresenter::setSelectedRole
 * @details 更新选中角色并刷新属性展示。
 * @param r 设备角色。
 */
void HardwareEditorPresenter::setSelectedRole(DeviceRole r)
{
    selectedRole_ = r;
    refreshAttrPanel();
}

/**
 * @brief HardwareEditorPresenter::setSpecificView
 * @details 绑定特有属性面板并立即加载当前角色数据。
 * @param spec 特有属性适配器。
 */
void HardwareEditorPresenter::setSpecificView(SpecificAttrPanelAdapter *spec)
{
    if (spec_ == spec)
        return;
    if (spec_)
        disconnect(spec_, nullptr, this, nullptr);
    spec_ = spec;
    if (spec_) {
        connect(spec_, &SpecificAttrPanelAdapter::specificEdited, this, &HardwareEditorPresenter::onSpecificEdited);
        // 切换tab或首次绑定时，立刻显示并灌入当前 role
        spec_->showRole(selectedRole_);
        spec_->loadFromDoc(doc_, selectedRole_);
    }
}

//点击设备
/**
 * @brief HardwareEditorPresenter::onNodeToggled
 * @details 节点切换时更新角色并刷新属性面板。
 * @param role 节点角色。
 * @param checked 是否选中。
 */
void HardwareEditorPresenter::onNodeToggled(DeviceRole role, bool checked)
{
    if (!checked)
        return;
    selectedRole_ = role;
    refreshAttrPanel();
    if (spec_) {
        spec_->showRole(role);
        spec_->loadFromDoc(doc_, role);
    }
}

// 特有属性写回 Model
/**
 * @brief HardwareEditorPresenter::onSpecificEdited
 * @details 根据角色及键值将特有属性写入模板。
 * @param role 设备角色。
 * @param key 属性键。
 * @param v 属性值。
 */
void HardwareEditorPresenter::onSpecificEdited(DeviceRole role, const QString &key, const QVariant &v)
{
    if (!doc_ || role == DeviceRole::Undefined)
        return;

    auto dv = v; // 便于 toDouble()/toInt()
    if (role == DeviceRole::SignalGenerator && doc_->d_Generator) {
        if (key == "SG.LevelMin")
            doc_->d_Generator->LevelMin = dv.toDouble();
        else if (key == "SG.LevelMax")
            doc_->d_Generator->LevelMax = dv.toDouble();
    } else if (role == DeviceRole::Amplifier && doc_->d_Amplifier) {
        if (key == "PA.InputLevelMax")
            doc_->d_Amplifier->InputLevelMax = dv.toDouble();
        else if (key == "PA.CouplerValue")
            doc_->d_Amplifier->CouplerValue = dv.toDouble();
        else if (key == "PA.CouplerType")
            doc_->d_Amplifier->CouplerType = dv.toInt();
        else if (key == "PA.CouplerTableFWDTableID")
            doc_->d_Amplifier->CouplerTableFWDTableID = dv.toInt();
        else if (key == "PA.CouplerTableREVTableID")
            doc_->d_Amplifier->CouplerTableREVTableID = dv.toInt();
    } else if ((role == DeviceRole::PowerMeterForward && doc_->d_FwdPowerMeter) || (role == DeviceRole::PowerMeterReverse && doc_->d_RevPowerMeter) || (role == DeviceRole::PowerMeterMonitor && doc_->d_MonPowerMeter)) {
        auto pm = (role == DeviceRole::PowerMeterForward ? doc_->d_FwdPowerMeter : role == DeviceRole::PowerMeterReverse ? doc_->d_RevPowerMeter
                                                                                                                         : doc_->d_MonPowerMeter);
        if (key == "PM.Channel")
            pm->DeviceChannel = dv.toString();
    } else if (role == DeviceRole::AntennaReceives && doc_->d_ReceivesAntenna) {
        if (key == "ANT.HFactorsTableID")
            doc_->d_ReceivesAntenna->HFactorsTableID = dv.toInt();
        else if (key == "ANT.VFactorsTableID")
            doc_->d_ReceivesAntenna->VFactorsTableID = dv.toInt();
    } else if (role == DeviceRole::FieldProbe && doc_->d_MonFieldProbes) {
        if (key == "FP.CorrectionXYZTableID")
            doc_->d_MonFieldProbes->CorrectionXYZTableID = dv.toInt();
    } else if (role >= DeviceRole::Connector_SIG2PA && role <= DeviceRole::Connector_Transducers2PM) {
        ConnectorConfigPtr c;
        switch (role) {
        case DeviceRole::Connector_SIG2PA:
            c = doc_->c_SIG2PA;
            break;
        case DeviceRole::Connector_FWD2PM:
            c = doc_->c_FWD2PM;
            break;
        case DeviceRole::Connector_REV2PM:
            c = doc_->c_REV2PM;
            break;
        case DeviceRole::Connector_PA2Transducers:
            c = doc_->c_PA2Transducers;
            break;
        case DeviceRole::Connector_Transducers2PM:
            c = doc_->c_Transducers2PM;
            break;
        default:
            break;
        }
        if (c) {
            if (key == "CON.ValueType")
                c->ValueType = dv.toInt();
            else if (key == "CON.AttValue")
                c->AttValue = dv.toDouble();
            else if (key == "CON.AttTableID")
                c->AttTableID = dv.toInt();
            else if (key == "CON.switchPath")
                c->switchPath = dv.toInt();
            else if (key == "CON.switchChannel")
                c->switchChannel = dv.toInt();
        }
    } else if ((role == DeviceRole::CurrentInjectionProbeInput && doc_->d_InjectionTransducer) || (role == DeviceRole::CurrentInjectionProbeMonitor && doc_->d_MonitoringTransducer)) {
        auto cp = (role == DeviceRole::CurrentInjectionProbeInput ? doc_->d_InjectionTransducer
                                                                  : doc_->d_MonitoringTransducer);
        if (key == "CP.TransducerTableID")
            cp->TransducerTableID = dv.toInt();
    }
}

//选择设备型号 绑定ConnectingWindow信号
/**
 * @brief HardwareEditorPresenter::onNodeModelSync
 * @details 连接图同步节点可选型号时更新面板并写回模型信息。
 * @param models 可选型号列表。
 * @param currentText 当前型号。
 */
void HardwareEditorPresenter::onNodeModelSync(const QStringList &models, const QString &currentText)
{
    if (!doc_ || !attr_ || selectedRole_ == DeviceRole::Undefined)
        return;
    attr_->setAvailableModels(models);
    attr_->setData(currentText, currentIfIndex(), currentAddress());
    if (auto cfg = getConfig(selectedRole_)) {
        cfg->gAttributes.Model = currentText;
        cfg->gAttributes.LibraryPath = DataManager::instance()->libraryPathForModel(currentText);
    }
    if (selectedRole_ >= DeviceRole::Connector_SIG2PA && selectedRole_ <= DeviceRole::Connector_Transducers2PM) {
        if (spec_)
            spec_->loadFromDoc(doc_, selectedRole_);
    }
}

//AttributePanelAdapter::modelEdited  已废弃
/**
 * @brief HardwareEditorPresenter::onModelEdited
 * @details 处理属性面板发出的型号修改。
 * @param model 新型号。
 */
void HardwareEditorPresenter::onModelEdited(const QString &model)
{
    if (auto cfg = getConfig(selectedRole_)) {
        cfg->gAttributes.Model = model;
        cfg->gAttributes.LibraryPath = DataManager::instance()->libraryPathForModel(model);
    }
}

/**
 * @brief HardwareEditorPresenter::onInterfaceEdited
 * @details 将接口类型变更写入配置。
 * @param idx 接口索引。
 */
void HardwareEditorPresenter::onInterfaceEdited(int idx)
{
    if (auto cfg = getConfig(selectedRole_))
        cfg->gAttributes.InterfaceType = static_cast<DeviceInterfaceType>(idx);
}

/**
 * @brief HardwareEditorPresenter::onAddressEdited
 * @details 将地址变更写回配置。
 * @param addr 地址字符串。
 */
void HardwareEditorPresenter::onAddressEdited(const QString &addr)
{
    if (auto cfg = getConfig(selectedRole_))
        cfg->gAttributes.InterfaceAddr = addr;
}

/**
 * @brief HardwareEditorPresenter::refreshAttrPanel
 * @details 根据当前角色刷新公共属性面板，并处理互斥角色。
 */
void HardwareEditorPresenter::refreshAttrPanel()
{
    if (!attr_)
        return;
    const bool valid = (selectedRole_ != DeviceRole::Undefined);
    attr_->setEnabled(valid);
    if (!valid)
        return;
    if (selectedRole_ == DeviceRole::FieldProbe) {
        auto cfg = getConfig(DeviceRole::AntennaReceives);
        cfg->gAttributes.Model = STR_NO_DEVICE;
        cfg->gAttributes.InterfaceAddr = "";
        cfg->gAttributes.InterfaceType = DeviceInterfaceType::tmp;
        cfg->gAttributes.LibraryPath = "";
        auto cfgM = getConfig(DeviceRole::PowerMeterMonitor);
        cfgM->gAttributes.Model = STR_NO_DEVICE;
        cfgM->gAttributes.InterfaceType = DeviceInterfaceType::tmp;
        cfgM->gAttributes.LibraryPath = "";
        auto cfgR = getConfig(DeviceRole::Receiver);
        cfgR->gAttributes.Model = STR_NO_DEVICE;
        cfgR->gAttributes.InterfaceType = DeviceInterfaceType::tmp;
        cfgR->gAttributes.LibraryPath = "";
    }
    if (selectedRole_ == DeviceRole::AntennaReceives) {
        auto cfg = getConfig(DeviceRole::FieldProbe);
        cfg->gAttributes.Model = STR_NO_DEVICE;
        cfg->gAttributes.InterfaceType = DeviceInterfaceType::tmp;
        cfg->gAttributes.LibraryPath = "";
    }
    if (selectedRole_ == DeviceRole::PowerMeterMonitor) {
        auto cfg = getConfig(DeviceRole::Receiver);
        cfg->gAttributes.Model = STR_NO_DEVICE;
        cfg->gAttributes.InterfaceType = DeviceInterfaceType::tmp;
        cfg->gAttributes.LibraryPath = "";
    }
    if (selectedRole_ == DeviceRole::Receiver) {
        auto cfg = getConfig(DeviceRole::PowerMeterMonitor);
        cfg->gAttributes.Model = STR_NO_DEVICE;
        cfg->gAttributes.InterfaceType = DeviceInterfaceType::tmp;
        cfg->gAttributes.LibraryPath = "";
    }

    QStringList models = DataManager::instance()->getDeviceModelList(selectedRole_);
    //同步列表
    attr_->setAvailableModels(models);
    attr_->setData(currentModel(), currentIfIndex(), currentAddress());
}

/**
 * @brief HardwareEditorPresenter::currentModel
 * @details 获取当前角色对应的设备型号。
 * @return 型号字符串。
 */
QString HardwareEditorPresenter::currentModel() const
{
    auto cfg = getConfig(selectedRole_);
    return cfg ? cfg->gAttributes.Model : QString();
}

/**
 * @brief HardwareEditorPresenter::currentIfIndex
 * @details 获取当前角色的接口类型索引。
 * @return 接口索引。
 */
int HardwareEditorPresenter::currentIfIndex() const
{
    auto cfg = getConfig(selectedRole_);
    return cfg ? static_cast<int>(cfg->gAttributes.InterfaceType) : 0;
}

/**
 * @brief HardwareEditorPresenter::currentAddress
 * @details 获取当前角色的接口地址。
 * @return 地址字符串。
 */
QString HardwareEditorPresenter::currentAddress() const
{
    auto cfg = getConfig(selectedRole_);
    return cfg ? cfg->gAttributes.InterfaceAddr : QString();
}

/**
 * @brief HardwareEditorPresenter::getConfig
 * @details 根据角色返回对应的配置对象。
 * @param role 设备角色。
 * @return 设备配置指针。
 */
DeviceConfigBasePtr HardwareEditorPresenter::getConfig(DeviceRole role) const
{
    if (!doc_)
        return {};
    switch (role) {
    case DeviceRole::SignalGenerator:
        return doc_->d_Generator;
    case DeviceRole::Amplifier:
        return doc_->d_Amplifier;
    case DeviceRole::PowerMeterForward:
        return doc_->d_FwdPowerMeter;
    case DeviceRole::PowerMeterReverse:
        return doc_->d_RevPowerMeter;
    case DeviceRole::PowerMeterMonitor:
        return doc_->d_MonPowerMeter;
    case DeviceRole::Receiver:
        return doc_->d_MonReceiver;
    case DeviceRole::AntennaReceives:
        return doc_->d_ReceivesAntenna;
    case DeviceRole::FieldProbe:
        return doc_->d_MonFieldProbes;
    case DeviceRole::CurrentInjectionProbeInput:
        return doc_->d_InjectionTransducer;
    case DeviceRole::CurrentInjectionProbeMonitor:
        return doc_->d_MonitoringTransducer;
    case DeviceRole::Connector_SIG2PA:
        return doc_->c_SIG2PA;
    case DeviceRole::Connector_FWD2PM:
        return doc_->c_FWD2PM;
    case DeviceRole::Connector_REV2PM:
        return doc_->c_REV2PM;
    case DeviceRole::Connector_PA2Transducers:
        return doc_->c_PA2Transducers;
    case DeviceRole::Connector_Transducers2PM:
        return doc_->c_Transducers2PM;
    default:
        return {};
    }
}
